<template>
  <div style="height: 100%">
    <el-table :data="paramsList" :default-expand-all="true" :row-key="'id'">
      <el-table-column prop="propName" label="属性名" :width="'300%'">
        <template #default="scope">
          <span v-if="showPropInput(scope.row)" class="no-select" style="width: 100%;">
            <el-input v-model="scope.row.propName" size="mini" style="width: 50%;" @blur="propBlur(scope.row)"/>
          </span>
          <span v-else class="no-select" style="color: blueviolet;">ITEMS</span>
        </template>
      </el-table-column>
      <el-table-column prop="valType" label="值类型">
        <template #default="scope">
          <el-select v-model="scope.row.valType" size="mini" :placeholder="''" @change="typeChange(scope.row)">
            <el-option
              v-for="type in getValTypeOption(scope.row)"
              :key="type.value"
              :label="type.label"
              :value="type.value"
            />
          </el-select>
        </template>
      </el-table-column>
      <el-table-column prop="val" label="值">
        <template #default="scope">
          <el-input v-if="scope.row.valType && scope.row.valType == 'string'" v-model="scope.row.val" size="mini"/>
        </template>
      </el-table-column>
      <el-table-column prop="remark" label="备注">
        <template #default="scope">
          <el-input v-model="scope.row.remark" size="mini"/>
        </template>
      </el-table-column>
      <el-table-column>
        <template slot="header">
          <el-button icon="el-icon-plus" round size="mini" type="primary" @click="addParams(null)"/>
        </template>
        <template #default="scope">
          <el-button
            v-if="scope.row.valType && scope.row.valType != 'string'"
            icon="el-icon-plus"
            round
            plain
            size="mini"
            type="primary"
            @click="addParams(scope.row)"
          />
          <el-button
            icon="el-icon-delete"
            round
            plain
            size="mini"
            type="danger"
            @click="deleteParam(scope.row)"
          />
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
import {cloneDeep} from "lodash-es";
import {getUUID} from "@/utils/common";

export default {
  name: "TemplateParams",
  props: {
    defaultData: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      paramsList: [],
      valTypeOption: [
        {
          label: '文本',
          value: 'string',
          color: '#e6f7ff'
        },
        {
          label: '对象',
          value: 'object',
          color: '#ffebee'
        },
        {
          label: '数组',
          value: 'array',
          color: '#f0f9eb'
        }
      ],
      errorRowList: []
    }
  },
  watch: {
    paramsList: {
      handler(newVal) {
        this.$emit('paramChange', cloneDeep(newVal))
      },
      deep: true
    }
  },
  mounted() {
    this.defaultData && this.defaultData.length && this.initParams(this.defaultData)
  },
  methods: {
    // 初始化参数
    initParams(data) {
      if (data && data.length) {
        this.paramsList = cloneDeep(data)
      }
    },
    // 新增参数
    addParams(row) {
      const base = {
        id: getUUID(),
        parentId: '',
        propName: '',
        valType: '',
        val: '',
        remark: '',
        sort: 0,
        children: []
      }
      if (row) {
        if (!row.children) {
          row.children = []
        }
        base.parentId = row.id
        base.sort = row.children.length
        if (row.valType == 'object') {
          base.valType = 'string'
        } else if (row.valType == 'array' && row.children.length) {
          base.valType = row.children[0].valType
        }
        row.children.push(base)
      } else {
        base.sort = this.paramsList.length
        this.paramsList.push(base)
      }
    },
    // 删除参数
    deleteParam(row) {
      this.removeNodeById(this.paramsList, row.id)
    },
    // 删除参数
    removeNodeById(data, idToRemove) {
      for (let i = 0; i < data.length; i++) {
        if (data[i].id === idToRemove) {
          data.splice(i, 1);
          return true;
        } else if (data[i].children && data[i].children.length > 0) {
          const found = this.removeNodeById(data[i].children, idToRemove);
          if (found) {
            return true;
          }
        }
      }
      return false;
    },
    // 根据id获取指定的树节点
    getNodeById(data, id) {
      for (let i = 0; i < data.length; i++) {
        if (data[i].id === id) {
          return data[i];
        } else if (data[i].children && data[i].children.length > 0) {
          const target = this.getNodeById(data[i].children, id)
          if (target) {
            return target
          }
        }
      }
    },
    // 值类型下拉选项
    getValTypeOption(row) {
      let result = []
      if (row.parentId) {
        const parent = this.getNodeById(this.paramsList, row.parentId)
        if (parent.valType == 'array') {
          if (parent.children && parent.children.length || !parent.children[0].valType) {
            result = this.valTypeOption.filter(item => item.value != parent.valType)
          } else {
            result = this.valTypeOption.filter(item => item.value == parent.children[0].valType)
          }
        } else {
          result = this.valTypeOption.filter(item => item.value == 'string')
        }
      } else {
        result = this.valTypeOption
      }
      return result
    },
    // 是否展示属性名输入框
    showPropInput(row) {
      let show = true
      if (row.parentId) {
        const parent = this.getNodeById(this.paramsList, row.parentId)
        show = parent.valType == 'object'
      }
      return show
    },
    // 值类型改变时触发
    typeChange(row) {
      row.children = []
    },
    // 属性值失去焦点时触发
    propBlur(row) {
      const err = function (that, data, row) {
        const exist = data.find(item => item.propName == row.propName)
        if (exist && exist.id != row.id) {
          that.errorRowList.push({
            id: row.id,
            err: '属性名' + row.propName + '已经存在，相同属性会被覆盖'
          })
        } else {
          that.errorRowList = that.errorRowList.filter(item => item.id != row.id)
        }
      }
      if (row.parentId) {
        const parent = this.getNodeById(this.paramsList, row.parentId)
        if (parent.children && parent.children.length) {
          err(this, parent.children, row)
        }
      } else {
        err(this, this.paramsList, row)
      }
    }
  }
}
</script>

<style scoped>
</style>
